import { useCallback, useState, useRef } from 'react';
import { useWebSocket } from './useWebSocketHook';
import { useChat } from './useChatContext';
import { generateUUID } from '../utils/common';
import { calculateFileHash } from '../utils/hashUtils';
import type { Message } from '../types';

interface UploadState {
  fileHash: string;
  fileName: string;
  fileSize: number;
  totalChunks: number;
  uploadedChunks: Set<number>;
  chunks: string[];
  isPaused: boolean;
  isCompleted: boolean;
  error?: string;
}

interface ResumableUploadOptions {
  maxRetries?: number;
  retryDelay?: number;
  onProgress?: (progress: number) => void;
  onComplete?: (fileHash: string) => void;
  onError?: (error: string) => void;
}

export const useResumableUpload = () => {
  const { sendMessage } = useWebSocket();
  const { state, dispatch } = useChat();
  const [uploads, setUploads] = useState<Map<string, UploadState>>(new Map());
  const [isUploading, setIsUploading] = useState(false);
  const retryTimeouts = useRef<Map<string, NodeJS.Timeout>>(new Map());

  // 生成文件哈希 - 使用新的hash计算工具，支持Web Worker和分片计算
  const generateFileHash = useCallback(async (file: File): Promise<string> => {
    console.log(`🔐 开始计算文件哈希: ${file.name} (${(file.size / 1024 / 1024).toFixed(2)}MB)`);
    
    const fileHash = await calculateFileHash(file, {
      useWorker: file.size > 1024 * 1024, // 大于1MB使用Worker
      chunkSize: 1024 * 1024, // 1MB分片
      onProgress: (progress) => {
        console.log(`🔐 哈希计算进度: ${file.name} - ${progress.toFixed(1)}%`);
      }
    });
    
    console.log(`🔐 文件哈希计算完成: ${file.name} -> ${fileHash}`);
    return fileHash;
  }, []);

  // 将文件分片
  const createFileChunks = useCallback(async (file: File): Promise<string[]> => {
    // 动态调整分片大小
    let CHUNK_SIZE;
    if (file.size < 10 * 1024 * 1024) { // 小于10MB
      CHUNK_SIZE = 512 * 1024; // 512KB chunks
    } else if (file.size < 100 * 1024 * 1024) { // 小于100MB
      CHUNK_SIZE = 2 * 1024 * 1024; // 2MB chunks
    } else { // 大于100MB
      CHUNK_SIZE = 5 * 1024 * 1024; // 5MB chunks
    }
    
    const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
    const chunks: string[] = [];
    
    for (let i = 0; i < totalChunks; i++) {
      const start = i * CHUNK_SIZE;
      const end = Math.min(start + CHUNK_SIZE, file.size);
      const chunk = file.slice(start, end);
      
      // 将chunk转换为base64
      const reader = new FileReader();
      const chunkData = await new Promise<string>((resolve) => {
        reader.onload = () => resolve(reader.result as string);
        reader.readAsDataURL(chunk);
      });
      
      chunks.push(chunkData.split(',')[1]); // 移除data:xxx;base64,前缀
    }
    
    return chunks;
  }, []);

  // 开始上传文件
  const startUpload = useCallback(async (
    file: File, 
    options: ResumableUploadOptions = {}
  ): Promise<string> => {
    if (!sendMessage) {
      throw new Error('WebSocket not connected');
    }

    if (!state.user) {
      throw new Error('User not set');
    }

    const fileHash = await generateFileHash(file);
    
    // 检查是否已经在上传中
    if (uploads.has(fileHash)) {
      const existingUpload = uploads.get(fileHash)!;
      if (!existingUpload.isCompleted && !existingUpload.isPaused) {
        throw new Error('File is already being uploaded');
      }
    }

    const chunks = await createFileChunks(file);
    
    // 创建上传状态
    const uploadState: UploadState = {
      fileHash,
      fileName: file.name,
      fileSize: file.size,
      totalChunks: chunks.length,
      uploadedChunks: new Set(),
      chunks,
      isPaused: false,
      isCompleted: false
    };

    setUploads(prev => new Map(prev).set(fileHash, uploadState));
    setIsUploading(true);

    // 创建本地文件消息
    const localFileMessage: Message = {
      id: generateUUID(),
      type: 'file',
      username: state.user.username,
      userId: state.user.userId,
      dateTime: new Date().toISOString(),
      timestamp: new Date(),
      randomColor: state.user.randomColor || '#000000',
      message: `正在上传文件: ${file.name}`,
      fileName: file.name,
      fileSize: file.size,
      fileType: file.type,
      fileHash: fileHash,
      uploadProgress: 0,
      isLocalUpload: true
    };
    
    dispatch({ type: 'ADD_MESSAGE', payload: localFileMessage });

    // 发送文件开始信息
    sendMessage({
      type: 'file-start',
      fileHash,
      fileName: file.name,
      fileSize: file.size,
      fileType: file.type,
      totalChunks: chunks.length,
      userId: state.user.userId,
      username: state.user.username,
      randomColor: state.user.randomColor,
      dateTime: new Date().toISOString()
    });

    // 开始上传分片
    await uploadChunks(fileHash, options);
    
    return fileHash;
  }, [sendMessage, state.user, generateFileHash, createFileChunks, uploads, dispatch]);

  // 上传分片
  const uploadChunks = useCallback(async (
    fileHash: string, 
    options: ResumableUploadOptions = {}
  ) => {
    const uploadState = uploads.get(fileHash);
    if (!uploadState || uploadState.isPaused || uploadState.isCompleted) {
      return;
    }

    const { maxRetries = 3, retryDelay = 1000 } = options;
    
    for (let i = 0; i < uploadState.totalChunks; i++) {
      // 检查是否已暂停或完成
      const currentState = uploads.get(fileHash);
      if (!currentState || currentState.isPaused || currentState.isCompleted) {
        break;
      }

      // 跳过已上传的分片
      if (uploadState.uploadedChunks.has(i)) {
        continue;
      }

      let retryCount = 0;
      let chunkUploaded = false;

      while (retryCount < maxRetries && !chunkUploaded) {
        try {
          // 发送分片
          sendMessage!({
            type: 'file-chunk',
            fileHash,
            chunkIndex: i,
            fileData: uploadState.chunks[i],
            totalChunks: uploadState.totalChunks,
            fileName: uploadState.fileName,
            userId: state.user?.userId || 'anonymous'
          });

          // 等待确认（这里简化处理，实际应该等待chunk-received消息）
          await new Promise(resolve => setTimeout(resolve, 100));
          
          // 标记分片已上传
          uploadState.uploadedChunks.add(i);
          chunkUploaded = true;

          // 更新进度
          const progress = (uploadState.uploadedChunks.size / uploadState.totalChunks) * 100;
          dispatch({
            type: 'UPDATE_MESSAGE_PROGRESS',
            payload: { fileHash, progress }
          });

          options.onProgress?.(progress);

        } catch (error) {
          retryCount++;
          console.warn(`分片 ${i} 上传失败，重试 ${retryCount}/${maxRetries}:`, error);
          
          if (retryCount < maxRetries) {
            await new Promise(resolve => setTimeout(resolve, retryDelay * retryCount));
          } else {
            const errorMsg = `分片 ${i} 上传失败，已达到最大重试次数`;
            setUploads(prev => {
              const newMap = new Map(prev);
              const state = newMap.get(fileHash);
              if (state) {
                state.error = errorMsg;
                state.isPaused = true;
              }
              return newMap;
            });
            options.onError?.(errorMsg);
            return;
          }
        }
      }
    }

    // 检查是否全部上传完成
    if (uploadState.uploadedChunks.size === uploadState.totalChunks) {
      setUploads(prev => {
        const newMap = new Map(prev);
        const state = newMap.get(fileHash);
        if (state) {
          state.isCompleted = true;
        }
        return newMap;
      });
      setIsUploading(false);
      options.onComplete?.(fileHash);
    }
  }, [uploads, sendMessage, state.user, dispatch]);

  // 暂停上传
  const pauseUpload = useCallback((fileHash: string) => {
    setUploads(prev => {
      const newMap = new Map(prev);
      const uploadState = newMap.get(fileHash);
      if (uploadState) {
        uploadState.isPaused = true;
      }
      return newMap;
    });

    // 清除重试定时器
    const timeout = retryTimeouts.current.get(fileHash);
    if (timeout) {
      clearTimeout(timeout);
      retryTimeouts.current.delete(fileHash);
    }
  }, []);

  // 恢复上传
  const resumeUpload = useCallback(async (
    fileHash: string, 
    options: ResumableUploadOptions = {}
  ) => {
    const uploadState = uploads.get(fileHash);
    if (!uploadState || uploadState.isCompleted) {
      return;
    }

    setUploads(prev => {
      const newMap = new Map(prev);
      const state = newMap.get(fileHash);
      if (state) {
        state.isPaused = false;
        state.error = undefined;
      }
      return newMap;
    });

    setIsUploading(true);
    await uploadChunks(fileHash, options);
  }, [uploads, uploadChunks]);

  // 取消上传
  const cancelUpload = useCallback((fileHash: string) => {
    setUploads(prev => {
      const newMap = new Map(prev);
      newMap.delete(fileHash);
      return newMap;
    });

    // 清除重试定时器
    const timeout = retryTimeouts.current.get(fileHash);
    if (timeout) {
      clearTimeout(timeout);
      retryTimeouts.current.delete(fileHash);
    }

    setIsUploading(false);
  }, []);

  // 获取上传进度
  const getUploadProgress = useCallback((fileHash: string): number => {
    const uploadState = uploads.get(fileHash);
    if (!uploadState) return 0;
    return (uploadState.uploadedChunks.size / uploadState.totalChunks) * 100;
  }, [uploads]);

  // 获取上传状态
  const getUploadState = useCallback((fileHash: string): UploadState | undefined => {
    return uploads.get(fileHash);
  }, [uploads]);

  return {
    startUpload,
    pauseUpload,
    resumeUpload,
    cancelUpload,
    getUploadProgress,
    getUploadState,
    isUploading,
    uploads: Array.from(uploads.values())
  };
};